package net.vsame.url2sql.web;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.vsame.url2sql.helper.Url2SqlContext;
import net.vsame.url2sql.helper.WebHelper;
import net.vsame.url2sql.render.JsonRender;
import net.vsame.url2sql.render.JsonpRender;
import net.vsame.url2sql.render.Render;
import net.vsame.url2sql.url.impl.UrlConfig;
import net.vsame.url2sql.url.impl.UrlMapping;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Url2SqlFilter implements Filter {
	
	private static Log LOG = LogFactory.getLog(Url2SqlFilter.class);
	private static String encoding = "utf-8";
	private static boolean enabledJsonp = true;

    public Url2SqlFilter() {
    }

	public void destroy() {
	}

	public void doFilter(ServletRequest _req, ServletResponse _resp, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) _req;
		HttpServletResponse response = (HttpServletResponse) _resp;
		// 设置编码
		request.setCharacterEncoding(encoding);
		response.setCharacterEncoding(encoding);
		try{
			WebHelper.init(request, response);
			String[] ext = new String[]{null};
			Url2SqlContext c = getContext(request.getRequestURI().substring(request.getContextPath().length()), ext);
			if(ext[0] == null){//不是默认的视图 放行 json jsonp有默认视图
				chain.doFilter(request, response);
			}else {
				//根据扩展名查找默认视图
				Render render = findDefaultRender(ext[0]);
				if(c == null){
					//没有对应上下文
				}else {
					//调用对应Action
					UrlMapping.getMapping().invoke();
					//优先用户视置的视图
					if(c.getRender() != null){
						render = c.getRender();
					}
				}
				
				//无视图则直接放行
				if(render != null){
					if(render.getEncoding() == null){
						render.setEncoding(encoding);//设置默认编码
					}
					render.setContext(request, response).render();
				}else {
					chain.doFilter(request, response);
				}
			}
		}finally{
			WebHelper.remove();
		}
	}
	
	/**
	 * 查找默认视图
	 * @param ext
	 * @return
	 */
	private Render findDefaultRender(String ext) {
		Render render = null;
			//根据扩展名寻找 
		if(ext.equals(".json")){
			render = new JsonRender();
		} else if(ext.equals(".jsonp")){
			render = new JsonpRender();
		}else {
			//默认为文件
		}
		return render;
	}

	private Url2SqlContext getContext(String requestURI, String[] ext){
		
		String[] urlNodes = requestURI.split("/");
		if(urlNodes.length==0){
			return null;
		}
		String last = urlNodes[urlNodes.length-1];
		String[] extensionNames = new String[]{".json", ".jsonp"};
		for(String s : extensionNames){
			if(last.endsWith(s)){
				ext[0] = s;
			}
		}
		if(!last.contains(".")){
			ext[0] = "";
		}
		if(ext[0] == null){
			return null; //不符合扩展名
		}
		String s = urlNodes[urlNodes.length-1];
		urlNodes[urlNodes.length-1] = s.substring(0, s.length() - ext[0].length());
		
		//寻找Action
		UrlMapping mapping = UrlMapping.getMapping();
		StringBuffer sb = new StringBuffer();
		UrlConfig c = null;
		for(int i=0; i<urlNodes.length; i++){
			if("".equals(urlNodes[i])){
				continue;
			}
			
			sb.append("/").append(urlNodes[i]);
			if(c == null){
				c = mapping.getConfig(sb.toString());
				if(c != null){
					requestURI = sb.toString();
					sb = new StringBuffer();//记录参数
				}
			}
		}
		if(c == null){
			return null; //没有对应Action
		}
		
		//创建上下文
		Url2SqlContext context = WebHelper.getContext();
		context.setExtensionName(ext[0]);
		context.setRequestUrl(requestURI);
		context.setUrlConfig(c);
		if(sb.length()>0){
			String str = sb.toString();
			context.setRestfulParam(str.substring(1, str.length()));
		}
		return context;
	}
	
	public void init(FilterConfig config) throws ServletException {
		encoding = config.getInitParameter("encoding");
		// 默认编码为UTF-8
		if (encoding == null || "".equals(encoding)) {
			encoding = "UTF-8";
		}
		String jsonp = config.getInitParameter("jsonp");
		if("false".equalsIgnoreCase(jsonp)){
			enabledJsonp = false;
		}
		LOG.info("url2sql core init. encoding:" + encoding + ". jsonp="+enabledJsonp);
		
		UrlMapping.getMapping().reload(); 
	}
}
